import * as REGL from 'regl';

export function test () {
  const regl = REGL(document.getElementById('canvas'));
  const drawTriangle = regl({

    // Shaders in regl are just strings.  You can use glslify or whatever you want
    // to define them.  No need to manually create shader objects.
    frag: `
      precision mediump float;
      uniform vec4 color;

      const int RAYCAST_STEPS = 100;
      const float RAYCAST_MIN = 1.0;
      const float RAYCAST_MAX = 20.0;
      const vec2 iResolution = vec2(1600.0, 1000.0);

      float sdSphere (vec3 p, float s) {
        return length(p)-s;
      }

      float map(vec3 pos) {
        float sdf = sdSphere(pos, .8);
        return sdf;
      }

      float raycast (in vec3 rayPos, in vec3 rayDir) {
        float t = RAYCAST_MIN;
        for(int i = 0; i < RAYCAST_STEPS; i++) {
          if (t > RAYCAST_MAX) {
            break;
          }
          float sdf = map(rayPos + rayDir * t);
          if (abs(sdf) < 0.0001 * t) {
            return t;
          }
          t += sdf;
        }
        return -1.0;
      }

      vec3 getNormal (vec3 pos) {
        vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
        return normalize( e.xyy*map(pos + e.xyy)+ 
                          e.yyx*map(pos + e.yyx)+ 
                          e.yxy*map(pos + e.yxy)+ 
                          e.xxx*map(pos + e.xxx)); 
      }

      vec3 render (vec3 cameraPos, vec3 dir) {
        vec3 col = vec3(0.7, 0.7, 0.9) - max(dir.y,0.0)*0.3;
        float t = raycast(cameraPos, dir);
    
        if (t >= .0) {
          vec3 pos = cameraPos + t * dir;
          return pos;
          // vec3 normal = getNormal(pos);
          // return vec3(normal);
        }
    
        return col;
      }

      mat3 setCamera( in vec3 pos, in vec3 target, float cr ) {
        vec3 cw = normalize(target-pos);
        vec3 cp = vec3(sin(cr), cos(cr),0.0);
        vec3 cu = normalize( cross(cw,cp) );
        vec3 cv =          ( cross(cu,cw) );
        return mat3( cu, cv, cw );
      }

      void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
        vec3 cameraTarget = vec3( .0, .0, .0 );
        vec3 cameraPos = cameraTarget + vec3(0, 0, 4.5);
        mat3 cameraMat = setCamera( cameraPos, cameraTarget, 0.0 );

        vec2 p = (2.0 * fragCoord - iResolution) / iResolution.y;
        vec3 rayDir = cameraMat * normalize(vec3(p, 2.5));

        vec3 color = render(cameraPos, rayDir);
        
        fragColor = vec4(color, 1.0);
      }

      void main() {
        vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
        mainImage(color, vec2(gl_FragCoord.x, gl_FragCoord.y));
        gl_FragColor = color;
      }
      
    `,
  
    vert: `
      precision mediump float;
      attribute vec2 position;
      void main() {
        gl_Position = vec4(position, 0, 1);
      }
    `,
  
    // Here we define the vertex attributes for the above shader
    attributes: {
      // regl.buffer creates a new array buffer object
      position: regl.buffer([
        [-1, -1],   // no need to flatten nested arrays, regl automatically
        [1, -1],    // unrolls them into a typedarray (default Float32)
        [1,  1],
        [-1, -1],   // no need to flatten nested arrays, regl automatically
        [1, 1],    // unrolls them into a typedarray (default Float32)
        [-1, 1],
      ])
      // regl automatically infers sane defaults for the vertex attribute pointers
    },
  
    uniforms: {
      // This defines the color of the triangle to be a dynamic variable
      color: regl.prop<{color: any}, 'color'>('color')
    },
  
    // This tells regl the number of vertices to draw in this command
    count: 6
  });
  
  // regl.frame() wraps requestAnimationFrame and also handles viewport changes
  // regl.frame(({time}) => {
  //   // clear contents of the drawing buffer
    
  // });
  regl.clear({
    color: [0, 0, 0, 0],
    depth: 1
  });

  // draw a triangle using the command defined above
  drawTriangle({
    color: [
      Math.cos(3),
      Math.sin(5),
      Math.cos(6),
      1
    ]
  });
}